package hn.cch.framework.util;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;


/**
 * BouncyCastleProvider
 *
 *
 *
 */
public class Sm4Util {

    private static Logger logger = LoggerFactory.getLogger(Sm4Util.class);

    private static final String algorithm = "SM4";
    private static final int mode = 1;
    private static final int size = 128;

    public enum CRYPT {
        EN,//加密
        DE//解密
    }

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public static byte[] key() {
        byte[] key = null;
        try {

            KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithm, BouncyCastleProvider.PROVIDER_NAME);
            keyGenerator.init(size, new SecureRandom());
            SecretKey secretKey = keyGenerator.generateKey();
            logger.info("Key algorithm : " + secretKey.getAlgorithm());
            key = secretKey.getEncoded();
            logger.info("Key Length : " + key.length);

        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return key;
    }

    /**
     * @param crypt 1：加密  2：解密
     * @param data  数据
     * @param key   密钥
     * @return
     */
    public static byte[] crypt(CRYPT crypt, byte[] data, byte[] key) {
        byte[] temp = null;
        try {

            Cipher cipher = Cipher.getInstance(algorithm, BouncyCastleProvider.PROVIDER_NAME);
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, algorithm);
            cipher.init(mode, secretKeySpec);
            // 加密或解密
            switch (crypt) {
                case EN:
                    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
                    break;
                case DE:
                    cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
                    break;
                default:
                    logger.error("crypt error : CRYPT.EN|CRYPT.DE");
            }
            // 数据处理
            temp = cipher.doFinal(data);
            // 异常处理
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return temp;
    }


}
